<template>
    <div class="threeBox" ref="threeBox" @dblclick="e => getEvent(e)">
        <div class="fps-counter" ref="fpsCounter">FPS: 0</div>
        <SceneTool :emitEditor="emitEditor"/>
    </div>
</template>

<script setup>
import {onMounted, onUnmounted, ref} from 'vue';
import * as THREE from 'three'
import {ThreeEditor, getDistanceScalePoint, createGsapAnimation} from 'three-editor-cores';
import SceneTool from './sceneTool.vue'

ThreeEditor.dracoPath = '/three-editor/dist/draco/'

const threeBox = ref(null)
const props = defineProps(['emitEditor', 'options'])
// FPS计数器引用
const fpsCounter = ref(null)
// FPS计算相关变量
let frameCount = 0
let lastTime = performance.now()
let fps = 0

// 墙绘制相关变量
const isWallCreationMode = ref(false)
let wallStartPoint = null
let tempWallLine = null
let raycaster = null
let mouse = new THREE.Vector2()

onMounted(() => (props.emitEditor.sceneName !== '') && createScene())

function getEvent(e) {
    // 如果处于墙创建模式，处理墙创建事件
    if (isWallCreationMode.value) {
        handleWallCreationClick(e)
        return
    }
    props.emitEditor.threeEditor.getSceneEvent(e, info => {
        props.emitEditor.info = info
        if (info.mode === '点击信息') {
            const {camera, controls} = props.emitEditor.threeEditor
            const p = getDistanceScalePoint(camera.position, info.point, 0.6)
            createGsapAnimation(camera.position, p)
            createGsapAnimation(controls.target, info.point)
        }
    })
}

// 切换墙创建模式
function toggleWallCreationMode() {
    isWallCreationMode.value = !isWallCreationMode.value
    if (isWallCreationMode.value) {
        // 进入墙创建模式
        initWallCreation()
    } else {
        // 退出墙创建模式
        cleanupWallCreation()
    }
}

// 初始化墙创建相关对象
function initWallCreation() {
    const {threeEditor} = props.emitEditor
    // 创建射线检测器
    raycaster = new THREE.Raycaster()
    // 添加鼠标移动事件监听
    threeEditor.DOM.addEventListener('mousemove', handleMouseMove)
    // 保存原始光标样式
    threeEditor.DOM.style.cursor = 'crosshair'
}

// 清理墙创建相关对象
function cleanupWallCreation() {
    const {threeEditor} = props.emitEditor
    // 移除鼠标移动事件监听
    threeEditor.DOM.removeEventListener('mousemove', handleMouseMove)
    // 恢复原始光标样式
    threeEditor.DOM.style.cursor = ''
    // 移除临时预览线
    if (tempWallLine && threeEditor.scene) {
        threeEditor.scene.remove(tempWallLine)
        tempWallLine.geometry.dispose()
        tempWallLine.material.dispose()
        tempWallLine = null
    }
    // 重置墙起点
    wallStartPoint = null
}

// 处理鼠标点击创建墙
function handleWallCreationClick(event) {
    const {threeEditor} = props.emitEditor

    // 计算鼠标在归一化设备坐标中的位置（-1到1之间）
    const rect = threeEditor.DOM.getBoundingClientRect()
    mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1
    mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1

    // 设置射线
    raycaster.setFromCamera(mouse, threeEditor.camera)
    // 创建一个水平面（y=0）用于检测交点
    const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0)
    const intersectionPoint = new THREE.Vector3()
    // 计算射线与平面的交点
    if (raycaster.ray.intersectPlane(plane, intersectionPoint)) {
        // 确保交点在水平面上
        intersectionPoint.y = 0
        if (!wallStartPoint) {
            // 第一次点击，设置起点
            wallStartPoint = intersectionPoint.clone()
        } else {
            // 第二次点击，创建墙
            createWall(wallStartPoint, intersectionPoint)
            // 移除临时预览线
            if (tempWallLine) {
                threeEditor.scene.remove(tempWallLine)
                tempWallLine.geometry.dispose()
                tempWallLine.material.dispose()
                tempWallLine = null
            }
            // 可以选择连续创建墙，这里设置起点为终点，以便继续创建
            wallStartPoint = intersectionPoint.clone()
        }
    }
}

// 处理鼠标移动，显示临时预览线
function handleMouseMove(event) {
    if (!wallStartPoint || !props.emitEditor.threeEditor) return
    const {threeEditor} = props.emitEditor
    // 计算鼠标在归一化设备坐标中的位置
    const rect = threeEditor.DOM.getBoundingClientRect()
    mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1
    mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1
    // 设置射线
    raycaster.setFromCamera(mouse, threeEditor.camera)
    // 创建一个水平面（y=0）用于检测交点
    const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0)
    const intersectionPoint = new THREE.Vector3()
    // 计算射线与平面的交点
    if (raycaster.ray.intersectPlane(plane, intersectionPoint)) {
        // 确保交点在水平面上
        intersectionPoint.y = 0
        // 移除之前的临时线
        if (tempWallLine) {
            threeEditor.scene.remove(tempWallLine)
            tempWallLine.geometry.dispose()
            tempWallLine.material.dispose()
        }
        // 创建新的临时预览线
        const lineGeometry = new THREE.BufferGeometry().setFromPoints([wallStartPoint, intersectionPoint])
        const lineMaterial = new THREE.LineBasicMaterial({ color: 0xff0000, linewidth: 2 })
        tempWallLine = new THREE.Line(lineGeometry, lineMaterial)
        threeEditor.scene.add(tempWallLine)
    }
}

// 创建墙
function createWall(startPoint, endPoint) {
    const {threeEditor} = props.emitEditor
    // 计算墙的方向和长度
    const direction = new THREE.Vector3().subVectors(endPoint, startPoint)
    const length = direction.length()
    // 确保墙有最小长度
    if (length < 0.1) {
        return
    }
    // 设置墙的高度和厚度
    const height = 3 // 墙的高度
    const thickness = 0.2 // 墙的厚度
    // 创建墙的几何体
    const wallGeometry = new THREE.BoxGeometry(length, height, thickness)
    // 创建墙的材质
    const wallMaterial = new THREE.MeshStandardMaterial({
        color: 0xCD853F, // 秘鲁棕色，常用于墙体
        roughness: 0.7,
        metalness: 0.1,
        side: THREE.DoubleSide
    })
    // 创建墙的网格
    const wallMesh = new THREE.Mesh(wallGeometry, wallMaterial)
    // 计算墙的中心位置
    const center = new THREE.Vector3().lerpVectors(startPoint, endPoint, 0.5)
    // 设置墙的位置（底部位于y=0）
    wallMesh.position.set(center.x, height / 2, center.z)
    // 计算墙的旋转角度 - 确保墙垂直于水平面
    // 设置方向向量的y分量为0，确保在XZ平面内
    direction.y = 0
    direction.normalize()
    // 创建一个参考向量（默认沿Z轴方向）
    const referenceDir = new THREE.Vector3(1, 0, 0)
    // 计算从参考方向到目标方向的旋转
    const quaternion = new THREE.Quaternion().setFromUnitVectors(referenceDir, direction)
    wallMesh.quaternion.copy(quaternion)
    // 将墙添加到场景中
    threeEditor.scene.add(wallMesh)
}

function createScene() {
    const sceneParams = {}
    // 创建Editor
    const threeEditor = new ThreeEditor(threeBox.value, {
            pixelRatio: window.devicePixelRatio * 2,
            webglRenderParams: {antialias: true, alpha: true, logarithmicDepthBuffer: true},
            sceneParams,
            // 优化缩放灵敏度
            controlsConfig: {
                zoomSpeed: 1.5 // 提高缩放速度，使鼠标滚轮滚动时缩放更灵敏
            }
        }
    )
    // 设置模型操作
    threeEditor.handler.mode = '变换'
    // 设置背景
    threeEditor.renderer.setClearColor('#00091c', 0.1)
    // 设置网格
    const grid = {
        showGrid: true,
        size: 700,
        divisions: 700,
        colorCenterLine: null,
        colorGrid: '#343f49',
        gridHelper: null
    }
    grid.gridHelper = new THREE.GridHelper(grid.size, grid.divisions, grid.colorCenterLine, grid.colorGrid)
    grid.gridHelper.name = 'GridHelper'
    threeEditor.scene.add(grid.gridHelper)
    // 设置更强的光照以提亮物体
    const isLight = threeEditor.scene.children.every(i => !i.isLight)
    if (isLight) {
      // 添加高强度环境光
      threeEditor.setLight('AmbientLight', { intensity: 1.5 })
      // 添加高强度方向光
      threeEditor.setLight('DirectionalLight', {
        intensity: 2.5,
        position: { x: 10, y: 10, z: 10 }
      })
    }

    // 默认为移动操作
    props.emitEditor.mode = '平移'
    props.emitEditor.openKey = threeEditor.handler.openKey
    props.emitEditor.selectPanelEnable = threeEditor.handler.selectPanelEnable
    // 添加DOM引用到threeEditor对象，用于鼠标事件处理
    threeEditor.DOM = threeBox.value
    // 禁用坐标轴和网格吸附功能
    if (threeEditor.transformControls) {
        threeEditor.transformControls.translationSnap = null;
        threeEditor.transformControls.rotationSnap = null;
        threeEditor.transformControls.scaleSnap = null;
    }
    // 隐藏坐标轴
    threeEditor.scene.traverse(child => {
        if (child.isAxesHelper || child.name === 'AxesHelper') {
            child.visible = false;
        }
    });
    // 使用requestAnimationFrame循环更新FPS显示
    function animate() {
        updateFPS();
        requestAnimationFrame(animate);
    }
    animate();
    props.emitEditor.threeEditor = threeEditor
    window.onresize = () => threeEditor.renderSceneResize()
}

// 更新FPS显示的函数
function updateFPS() {
    frameCount++;
    const currentTime = performance.now();
    const deltaTime = currentTime - lastTime;
    if (deltaTime >= 1000) { // 每秒更新一次
        fps = Math.round(frameCount * 1000 / deltaTime);
        frameCount = 0;
        lastTime = currentTime;
        if (fpsCounter.value) {
            fpsCounter.value.textContent = `FPS: ${fps}`;
        }
    }
}
props.emitEditor.createScene = createScene
// 暴露墙绘制模式切换函数给父组件
props.emitEditor.toggleWallCreationMode = toggleWallCreationMode
// 销毁
onUnmounted(() => props.emitEditor.threeEditor?.destroySceneRender())
</script>
<style lang="less" scoped>
.threeBox {
    height: 100%;
    width: 100%;
    position: relative;

    .fps-counter {
        position: absolute;
        top: 60px;
        right: 265px;
        background-color: rgba(0, 0, 0, 0.7);
        color: #ffffff;
        padding: 5px 10px;
        border-radius: 4px;
        font-size: 14px;
        font-family: monospace;
        z-index: 1000;
        pointer-events: none;
    }
}
</style>
